package com.ccteam.fluidmusic.ui.nowplaying

import android.app.Application
import android.graphics.Color
import android.support.v4.media.session.PlaybackStateCompat
import androidx.lifecycle.*
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.core.TaglibParser
import com.ccteam.fluidmusic.fluidmusic.common.MusicServiceConnectionFlow
import com.ccteam.fluidmusic.fluidmusic.common.utils.isLocalMedia
import com.ccteam.fluidmusic.fluidmusic.core.SettingCore
import com.ccteam.fluidmusic.utils.*
import com.ccteam.fluidmusic.view.bean.*
import com.ccteam.fluidmusic.widget.LyricsRecyclerView
import com.ccteam.model.Resource
import com.ccteam.shared.domain.music.MusicLyricsDataUseCase
import com.ccteam.shared.result.BaseItemData
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.FileNotFoundException
import javax.inject.Inject

/**
 *
 * @author Xiaoc
 * @since 2021/1/5
 *
 * 正在播放界面的ViewModel
 * 此ViewModel负责观察当前播放内容和状态，然后做对应UI相应的转变
 * 大部分正在播放逻辑转交给了 [MainActivityViewModel] 因为两者代码大体相同
 */
@HiltViewModel
class NowPlayingViewModel @Inject constructor(
    private val settingCore: SettingCore,
    private val musicLyricsDataUseCase: MusicLyricsDataUseCase,
    private val taglibParser: TaglibParser,
    application: Application,
    musicServiceConnectionFlow: MusicServiceConnectionFlow
): AndroidViewModel(application) {

    private val _fluidColor = MediatorLiveData<Pair<Int,Int>>()
    val fluidColor: LiveData<Pair<Int,Int>> get() = _fluidColor

    /**
     * 是否开启取色逻辑，默认为false
     */
    var shouldEnablePalette = false

    /**
     * 是否开启流动特效模式，默认true开启
     */
    private val _enableFluidMode = MutableLiveData(true)
    val enableFluidMode: LiveData<Boolean> get() = _enableFluidMode

    val playbackStateLiveData: LiveData<PlaybackStateCompat> = musicServiceConnectionFlow.nowPlaybackState
        .asLiveData()

    /**
     * 歌词是否加载中
     */
    private val _lyricsLoading = MutableLiveData<LoadMessage>()
    val lyricsLoading: LiveData<LoadMessage> get() = _lyricsLoading

    /**
     * 歌词内容
     * 使用 String 存储当前mediaId
     * 因为 nowPlaying 的内容会在同一首歌曲时也会发生变化
     * 一旦mediaId相同，不进行歌词内容的获取
     */
    private val _lyricsList = MutableLiveData<Triple<String,List<BaseItemData>,Boolean>>()
    val lyricsList : LiveData<Triple<String,List<BaseItemData>,Boolean>> = _lyricsList

    private val _lyricsConfig = MutableLiveData<LyricsRecyclerView.Config>()
    val lyricsConfig: LiveData<LyricsRecyclerView.Config> get() = _lyricsConfig

    var defaultColor: Pair<Int,Int> = Pair(Color.WHITE,Color.WHITE)

    init {
        /**
         * 监听设置的歌词大小变化
         */
        viewModelScope.launch {
            settingCore.enableFluidMode.collectLatest { enableFluidMode ->
                // 设置是否开启取色逻辑
                shouldEnablePalette = enableFluidMode == false
                _enableFluidMode.setValueIfNew(
                    enableFluidMode
                )
            }
        }

        _fluidColor.addSource(_enableFluidMode){
            _fluidColor.value = defaultColor
        }

        viewModelScope.launch {
            settingCore.lyricTextSize.collectLatest { lyricsTextSize ->
                _lyricsConfig.value = LyricsRecyclerView.Config(
                    application.resources.getDimension(R.dimen.lyrics_defult_text_size) * lyricsTextSize * 0.02f
                )
            }
        }

    }

    /**
     * 设置FluidColor的默认颜色
     * 当且仅当值为空时才设置
     */
    fun setDefaultFluidColor(colorPair: Pair<Int,Int>){
        if(_fluidColor.value == null){
            _fluidColor.value = colorPair
        }
    }

    fun setFluidColor(colorPair: Pair<Int,Int>){
        _fluidColor.value = colorPair
    }

    fun resetFluidColor(){
        _fluidColor.value = defaultColor
    }


    /**
     * 根据musicId加载对应歌词内容
     */
    fun loadLyrics(mediaData: NowPlayingMediaData){
        if(mediaData.mediaId == _lyricsList.value?.first){
            return
        }
        // 清除现有歌词
        _lyricsList.value = Triple("", emptyList(),false)
        _lyricsLoading.value = LoadMessage.Loading

        if(mediaData.mediaUri.toString().isEmpty()){
            _lyricsLoading.value = LoadMessage.Empty
            return
        }

        // 如果是本地媒体资源，则尝试获取内嵌歌词
        if(mediaData.mediaUri.isLocalMedia()){
            parseMediaTagLyrics(mediaData)
        } else {
            parseOnlineLyrics(mediaData.mediaId)
        }

    }

    /**
     * 获取在线音乐歌词
     */
    private fun parseOnlineLyrics(mediaId: String){
        viewModelScope.launch {
            val result = musicLyricsDataUseCase(mediaId)
            if(result is Resource.Success){
                if(result.data.isNullOrEmpty()){
                    _lyricsLoading.value = LoadMessage.Empty
                    return@launch
                }
                // 成功获取到歌词，进行解析
                _lyricsLoading.value = LoadMessage.Success
                val lyricsResult = LyricsUtils.parseLyrics(
                    result.data!!
                )
                _lyricsList.postValue(Triple(
                    mediaId,lyricsResult.second,lyricsResult.first
                ))
            } else {
                _lyricsLoading.value = LoadMessage.Error(ErrorMessage(result.message,result.errorCode))
            }
        }
    }

    /**
     * 通过Taglib解析本地音乐内嵌歌词
     */
    private fun parseMediaTagLyrics(mediaData: NowPlayingMediaData){
        val application = getApplication<Application>()
        viewModelScope.launch(Dispatchers.IO) {
            try {
                // 打开媒体文件的描述符
                application.contentResolver.openFileDescriptor(mediaData.mediaUri,"r")?.use {
                    val lyrics = taglibParser.getLyricsByTaglib(it.detachFd())

                    if(lyrics.isEmpty()){
                        _lyricsLoading.postValue(LoadMessage.Empty)
                        return@launch
                    }

                    // 如果存在内嵌歌词，则进行填充
                    val lyricsResult = LyricsUtils.parseLyrics(
                        lyrics
                    )
                    if(lyricsResult.second.isNullOrEmpty()){
                        _lyricsLoading.postValue(LoadMessage.Empty)
                    } else {
                        // 延迟500ms显示歌词，这样防止正在切换Tab栏导致的意外卡顿
                        delay(500L)
                        _lyricsLoading.postValue(LoadMessage.Success)
                        _lyricsList.postValue(Triple(
                            mediaData.mediaId,lyricsResult.second,lyricsResult.first
                        ))
                    }

                }
            } catch (e: FileNotFoundException){
                _lyricsLoading.postValue(LoadMessage.Empty)
            }
        }
    }
}